/* Copyright © 2010 LPRM
Universidade Federal do Espírito Santo - RNP-GT CWTools

This file is part of GW-Android.

GW-Android is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

GW-Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with GW-Android. If not, see <http://www.gnu.org/licenses/>. */
package br.ufes.cwtools.gw.android;

import java.io.InputStream;
import java.util.ArrayList;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.io.IOUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import br.ufes.cwtools.gw.android.components.ComponentDefinition;

import android.util.Log;

public class ComponentsParser {
	private ComponentsParser() {
		/* Prevents instantiation. */
	}
	
	public static ArrayList<ComponentDefinition> parse(InputStream source) {
		try {
			SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
			ApplicationHandler handler = new ApplicationHandler();
			parser.parse(source, handler);
			return handler.getComponents();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} 
	}
	
	public static ArrayList<ComponentDefinition> parse(String source) {
		return parse(IOUtils.toInputStream(source));
	}
	
	private static class ApplicationHandler extends DefaultHandler {
		private static final String LOG_TAG = "XmlParser";
		
		private static final String COMPONENT = "Component";
		private static final String COMPONENT_SETTING = "Setting";
		private static final String COMPONENT_NEXT = "NextComponent";
		
		public ArrayList<ComponentDefinition> components;
		private ComponentDefinition currentComponent = null;
		
		public ArrayList<ComponentDefinition> getComponents() {
			return components;
		}
		
		@Override
		public void startDocument() throws SAXException {
			super.startDocument();
			components = new ArrayList<ComponentDefinition>();
		}
		
		@Override
		public void startElement(String uri, String localName, String qName,
				Attributes attributes) throws SAXException {
			super.startElement(uri, localName, qName, attributes);
			
			if (localName.equalsIgnoreCase(COMPONENT)) {
				final String tag = attributes.getValue("tag");
				final String action = attributes.getValue("action");
				final String label = attributes.getValue("menuLabel");
				final String packageName = attributes.getValue("package");
				final String baseUrl = attributes.getValue("baseUrl");
				
				if (tag != null && action != null && packageName != null) {
					currentComponent = new ComponentDefinition(tag, action, label, packageName, baseUrl);
				} else Log.d(LOG_TAG, "One or more attributes missing for element " + COMPONENT + ".");
				
			} else if (localName.equalsIgnoreCase(COMPONENT_SETTING)) {
				final String key = attributes.getValue("key");
				final String value = attributes.getValue("value");
				
				if (key != null && value != null) {
					if (currentComponent != null) {
						currentComponent.putExtra(key, value);
					} else Log.d(LOG_TAG, COMPONENT_SETTING + " element found outside " + COMPONENT + ".");
				} else Log.d(LOG_TAG, "Attributes missing for element " + COMPONENT_SETTING + ".");
				
			} else if (localName.equalsIgnoreCase(COMPONENT_NEXT)) {
				final String tag = attributes.getValue("tag");
				final String relatedExtra = attributes.getValue("relatedExtra");
				String label = attributes.getValue("label");
				if (label == null) label = "";
				
				if (tag != null && relatedExtra != null) {
					if (currentComponent != null) {
						currentComponent.addRelatedComponent(tag, label, relatedExtra);
					} else Log.d(LOG_TAG, COMPONENT_NEXT + " element found outside " + COMPONENT + ".");
				} else Log.d(LOG_TAG, "One or more attributes missing for element " + COMPONENT_NEXT + ".");
			}
		}
		
		@Override
		public void endElement(String uri, String localName, String qName)
				throws SAXException {
			super.endElement(uri, localName, qName);
			
			if (localName.equalsIgnoreCase(COMPONENT)) {
				if (currentComponent != null) {
					components.add(currentComponent);
					currentComponent = null;
				}
			}
		}
	}
}

